package com.quanz.ckgl.mvc;

import static org.crank.crud.criteria.Comparison.eq;
import static org.crank.crud.criteria.Comparison.like;

import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.crank.crud.criteria.Criterion;
import org.crank.crud.criteria.Group;
import org.crank.crud.criteria.OrderBy;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.quanz.ckgl.services.ImageInfo;
import com.quanz.ckgl.services.Product;
import com.quanz.ckgl.services.ProductService;

/**
 * 产品管理Controlller
 * 
 * @author James Quan
 * @version 2015年10月10日 下午9:39:15
 */
@RestController
public class ProductController {

	private ProductService productService;

	@Autowired
	public void setProductService(ProductService productService) {
		this.productService = productService;
	}

	@RequestMapping(value = "/products_processing.json", method = { RequestMethod.GET, RequestMethod.POST })
	public DataTablesResponse products_processing(@ModelAttribute DataTablesRequest request) {
		DataTablesSearch search = request.getSearch();
		Criterion criterion = null;
		if (search != null && !StringUtils.isEmpty(search.getValue())) {
			String v = "%" + search.getValue() + "%";
			criterion = Group.or(like("id", v), like("name", v), like("vendor", v), like("phone", v));
		}
		int count = productService.findProductCount(criterion);
		DataTablesResponse resp = new DataTablesResponse();
		resp.setDraw(request.getDraw());
		resp.setRecordsFiltered(count);
		resp.setTotalRecords(count);
		if (count > 0) {
			DataTablesOrder[] orders = request.getOrder();
			OrderBy[] orderBy = null;
			if (orders != null && orders.length > 0) {
				DataTablesColumn[] columns = request.getColumns();
				orderBy = new OrderBy[orders.length];
				for (int i = 0; i < orders.length; i++) {
					DataTablesOrder order = orders[i];
					String column = columns[order.getColumn()].getData();
					orderBy[i] = "asc".equals(order.getDir()) ? OrderBy.asc(column) : OrderBy.desc(column);
				}
			}
			Product[] products = productService.findProduct(orderBy, request.getStart(), request.getLength(),
					criterion);
			resp.setData(products);
		} else {
			resp.setData(new Product[0]);
		}
		return resp;
	}

	@RequestMapping("/product/unused")
	public boolean checkProductIdUnused(@RequestParam("id") String id) {
		return productService.findProductCount(eq("id", id)) == 0;
	}

	@RequestMapping("/product/barcode/{barcode}")
	public Product getProductByBarcode(@PathVariable String barcode) {
		Product product = productService.findProductByBarcode(barcode);
		return product;
	}
	
	@RequestMapping("/product/{id}")
	public Product getProductById(@PathVariable String id) {
		Product product = productService.findProductById(id);
		return product;
	}

	@RequestMapping(value = "/product", method = RequestMethod.POST)
	public Product createProduct(Product product) {
		Product newProduct = productService.createProduct(product);
		return newProduct;
	}

	@RequestMapping(value = "/product/{id}", method = RequestMethod.PUT)
	public boolean updateProduct(@PathVariable String id, @ModelAttribute Product product) {
		Product p = productService.findProductById(id);
		if (p == null) {
			throw new IllegalArgumentException("product " + id + " not found!");
		}
		p = new Product(p);
		p.setName(product.getName());
		p.setVendor(product.getVendor());
		p.setPhone(product.getPhone());
		p.setCatalog(product.getCatalog());
		p.setColor(product.getColor());
		p.setUnit(product.getUnit());
		p.setSpec(product.getSpec());
		p.setBarcode(product.getBarcode());
		productService.updateProduct(p);
		return true;
	}

	@RequestMapping(value = "/product/{id}", method = RequestMethod.DELETE)
	public boolean removeProduct(@PathVariable String id) {
		Product product = productService.findProductById(id);
		if (product != null) {
			productService.removeProduct(product);
			return true;
		} else {
			return false;
		}
	}

	@RequestMapping(value = "/product/{id}/images.json")
	public ImageInfo[] images(@PathVariable String id) {
		ImageInfo[] infos = productService.findProductImages(id);
		return infos;
	}

	@RequestMapping(value = "/product/uploadImage", method = RequestMethod.POST)
	public ImageInfo uploadImage(@RequestParam("id") String id, @RequestParam("file") MultipartFile file)
			throws IOException {
		ImageInfo[] infos = productService.findProductImages(id);
		int max = 0;
		for (ImageInfo info : infos) {
			String name = info.getName();
			int i = NumberUtils.toInt(FilenameUtils.getBaseName(name));
			if (i > max) {
				max = i;
			}
		}
		String ext = FilenameUtils.getExtension(file.getOriginalFilename());
		String name = Integer.toString(max + 1) + (StringUtils.isEmpty(ext) ? "" : ("." + ext));
		ImageInfo info = new ImageInfo();
		info.setProductId(id);
		info.setName(name);
		info.setMimeType(file.getContentType());
		info.setSize(file.getSize());
		info.setLastModified(DateTime.now());
		InputStream in = file.getInputStream();
		try {
			info = productService.createImage(info, in);
		} finally {
			IOUtils.closeQuietly(in);
		}
		return info;
	}

	@RequestMapping(value = "/product/{id}/{name}", method = RequestMethod.DELETE)
	public boolean removeImage(@PathVariable String id, @PathVariable String name) {
		ImageInfo info = productService.findProductImageByName(id, name);
		if (info == null) {
			return false;
		}
		productService.removeImage(info);
		return true;
	}

	@RequestMapping(value = "/product/{id}/{name:.+}", method = RequestMethod.GET)
	public ResponseEntity<Resource> downloadImage(@PathVariable("id") String id, @PathVariable("name") String name)
			throws IOException {
		ImageInfo info = productService.findProductImageByName(id, name);
		if (info == null) {
			return new ResponseEntity<Resource>(HttpStatus.NOT_FOUND);
		}
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.parseMediaType(info.getMimeType()));
		headers.setContentLength(info.getSize());
		headers.setLastModified(info.getLastModified().getMillis());
		InputStream in = productService.getProductImage(info.getId());
		return new ResponseEntity<Resource>(new InputStreamResource(in), headers, HttpStatus.OK);
	}

}
